﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using MetaFrameCOM;
using System.Configuration;

namespace XenAppServices.ServiceLibrary.XenApp5
{
    public class XAServicesService : IXAServicesService
    {
        /// <summary>
        /// Get XenApp sessions for the specified user
        /// </summary>
        /// <param name="username">Username</param>
        /// <returns></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> GetSessionsByUsername(string currentUsername)
        {
            if (currentUsername.Contains("\\"))
            {
                currentUsername = currentUsername.Split('\\')[1];
                
            }

            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> sessions =
                new System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession>();

            IMetaFrameUser5 user = new MetaFrameCOM.MetaFrameUser();

            try
            {
                user.Initialize(
                    MFAccountAuthorityType.MFAccountAuthorityNTDomain,
                    System.Environment.UserDomainName,
                    MetaFrameAccountType.MFAccountDomainUser,
                    currentUsername);
            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }

            int i = 0;
            foreach (IMetaFrameSession s in user.Sessions)
            {
                XenAppServices.Classes.XASession session = new XenAppServices.Classes.XASession();
                session.Application = getApplicationName(s.Applications, i++);
                session.ClientName = s.ClientName;
                session.LogonTime = ToDateTime(s.get_LogonTime(-5));
                session.ServerName = s.ServerName;
                session.SessionName = s.SessionName;
                session.SessionID = s.SessionID;
                session.SessionState = getSessionState(s.SessionState);
                session.Username = s.UserName;

                sessions.Add(session);
            }
            

            return sessions;
        }

        /// <summary>
        /// Get XenApp sessions on a server
        /// </summary>
        /// <param name="serverName">Server</param>
        /// <returns></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> GetSessionsByServername(string serverName)
        {
            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession> sessions =
                new System.Collections.ObjectModel.Collection<XenAppServices.Classes.XASession>();

            IMetaFrameServer5 server = new MetaFrameCOM.MetaFrameServer();

            try
            {
                server.Initialize(MetaFrameObjectType.MetaFrameWinSrvObject, serverName);
            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }

            int i = 0;
            foreach (IMetaFrameSession s in server.Sessions)
            {
                XenAppServices.Classes.XASession session = new XenAppServices.Classes.XASession();
                session.Application = getApplicationName(s.Applications, i++);
                session.ClientName = s.ClientName;
                session.LogonTime = ToDateTime(s.get_LogonTime(-5));
                session.ServerName = s.ServerName;
                session.SessionName = s.SessionName;
                session.SessionID = s.SessionID;
                session.SessionState = getSessionState(s.SessionState);
                session.Username = s.UserName;

                sessions.Add(session);
            }


            return sessions;
        }

        /// <summary>
        /// Logs off a user session
        /// </summary>
        /// <param name="serverName">Server</param>
        /// <param name="sessionName">Session Name</param>
        /// <param name="sessionId">Session Id</param>
        public void LogoffSession(
            string serverName,
            string sessionName,
            int sessionId)
        {
            IMetaFrameSession5 s = new MetaFrameCOM.MetaFrameSessionClass();
            s.Initialize(
                MetaFrameObjectType.MetaFrameWinSrvObject,
                serverName,
                sessionName,
                sessionId);

            s.Logoff(0);
        }

        /// <summary>
        /// Returns the current version of the service
        /// </summary>
        /// <returns></returns>
        public string GetVersion()
        {
            Version ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

            return string.Format("{0}.{1}", ver.Major, ver.Minor);
        }

        /// <summary>
        /// Returns a collection of XenApp servers in a farm
        /// </summary>
        /// <returns>System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAServer></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAServer> GetXAServers()
        {
            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAServer> servers =
                new System.Collections.ObjectModel.Collection<Classes.XAServer>();

            try
            {
                IMetaFrameFarm6 farm = new MetaFrameFarm();
                farm.Initialize(MetaFrameObjectType.MetaFrameWinFarmObject);

                foreach (IMetaFrameServer5 server in farm.Servers)
                {
                    XenAppServices.Classes.XAServer s = new Classes.XAServer();
                    s.Hostname = server.ServerName;

                    s.IPAddress = server.IPAddress.ToString();

                    servers.Add(s);
                }
            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }
            
            return servers;
        }

        /// <summary>
        /// Returns a collection of XenApp applications in a farm
        /// </summary>
        /// <returns>System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAApplication></returns>
        public System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAApplication> GetFarmApplications()
        {
            System.Collections.ObjectModel.Collection<XenAppServices.Classes.XAApplication> applications =
                new System.Collections.ObjectModel.Collection<Classes.XAApplication>();

            try
            {
                IMetaFrameFarm6 farm = new MetaFrameFarm();
                farm.Initialize(MetaFrameObjectType.MetaFrameWinFarmObject);

                foreach (IMetaFrameApplication5 app in farm.Applications)
                {
                    //app.LoadData(0);
                    XenAppServices.Classes.XAApplication a = new Classes.XAApplication();
                    a.Name = app.BrowserName2;
                    //a.Folder = app.WinAppObject5.PNFolder;
                    applications.Add(a);
                }
            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }

            return applications;
        }

        private string getApplicationName(IMetaFrameApplications apps, int i)
        {
            string appName = string.Empty;

            try
            {
                if (apps.Count > i)
                {
                    IMetaFrameWinApp5 app = (IMetaFrameWinApp5)apps.get_Item(i);
                    app.LoadData();
                    appName = app.AppName;
                }
            }
            catch (ApplicationException ex)
            {
                throw new FaultException<ApplicationException>(
                        ex,
                        new FaultReason(ex.Message),
                        new FaultCode("Sender")
                    );
            }

            return appName;
        }

        private DateTime ToDateTime(IMetaFrameTime mfTime)
        {
            DateTime dt = DateTime.Today;

            try
            {
                int year = mfTime.Year;
                int month = mfTime.Month;
                int day = mfTime.Day;
                int hour = mfTime.Hour;
                int minute = mfTime.Minute;
                int second = mfTime.Second;

                dt = new DateTime(year, month, day, hour, minute, second);
            }
            catch (Exception ex)
            {
            }

            return dt;
        }

        private XenAppServices.Classes.SessionState getSessionState(MetaFrameSessionState state)
        {
            XenAppServices.Classes.SessionState sessionState = XenAppServices.Classes.SessionState.Unknown;

            switch (state)
            {
                case MetaFrameSessionState.MFSessionStateActive:
                    sessionState = XenAppServices.Classes.SessionState.Active;
                    break;
                case MetaFrameSessionState.MFSessionStateConnected:
                    sessionState = XenAppServices.Classes.SessionState.Connected;
                    break;
                case MetaFrameSessionState.MFSessionStateConnecting:
                    sessionState = Classes.SessionState.Connecting;
                    break;
                case MetaFrameSessionState.MFSessionStateDisconnected:
                    sessionState = XenAppServices.Classes.SessionState.Disconnected;
                    break;
                case MetaFrameSessionState.MFSessionStateDown:
                    sessionState = Classes.SessionState.Down;
                    break;
                case MetaFrameSessionState.MFSessionStateIdle:
                    sessionState = XenAppServices.Classes.SessionState.Idle;
                    break;
                case MetaFrameSessionState.MFSessionStateInit:
                    sessionState = Classes.SessionState.Init;
                    break;
                case MetaFrameSessionState.MFSessionStateListening:
                    sessionState = Classes.SessionState.Listening;
                    break;
                case MetaFrameSessionState.MFSessionStateResetting:
                    sessionState = Classes.SessionState.Resetting;
                    break;
                case MetaFrameSessionState.MFSessionStateShadowing:
                    sessionState = Classes.SessionState.Shadowing;
                    break;
                case MetaFrameSessionState.MFSessionStateUnknown:
                    sessionState = XenAppServices.Classes.SessionState.Unknown;
                    break;
            }

            return sessionState;
        }

    }
}
